【レポート】サービスメッシュは本当に必要なのか、何を解決するのか #AWSSummit
こんにちわ、札幌のヨシエです。 AWS Summit Tokyo 2019 3日目のA3-03で行われたセッションのレポートを書きましたのでご査収頂ければと思います。
登壇者
アマゾン ウェブ サービス ジャパン株式会社 技術統括本部 ソリューションアーキテクト 原 康紘
AWS 上でのマネージド・サービスメッシュを実現する AWS App Mesh や、Kubernetes ワークロードとの親和性が高い Istio など、サービスメッシュの世界には数々のプロダクトやソリューション、アイデアが生まれつつあります。本セッションでは、マイクロサービスにおけるベストプラクティスの集大成とも言えるサービスメッシュについて、その解決すべき課題と人々が熱狂する理由、サービスメッシュそのものの必要性について掘り下げます。同時に、サービスメッシュを実現する上で最も重要なコンポーネントの一つとも言える Envoy の詳細にも触れながら、皆さまがサービスメッシュを活用する手助けとなるヒントを紹介します。
最初に
本セッションの説明をする例として以下のようなシステム構成のサービスが存在するとする。
LB → App → DB
- サービスが成長するのあたって、サービスの安定提供や機能追加が実施された結果、Appの規模が大きくなることと小さい障害が頻発をし始め、そのうち障害が目立つようになる
- こういったサービス状況に対して「マイクロサービス化」しようと提案が入る
- この提案が発案された時から「モノリス(モノリシック)なアプリケーション」と呼ばれる(扱われる)ようになる
そもそもMonolithという呼称に込められるニュアンス
そもそも、どういったことが見えることでモノリスと呼ばれるようになるのか?
関係者調整のオーバーヘッド
- アプリケーションの開発が進むと、関わる人数が増えて調整ごとが増える
- モジュールの依存関係によってデプロイ実施のタイミング調整
- 別チームの開発部分が未完の状態に陥ることによる、スケジュール延期
- 変更による影響範囲の広さ
- 機能などのコード変更による影響範囲が広くなる
- モジュール構造維持の難しさ
- 構築時から時間が経つに連れて、上記の要因も含めモジュール構造を保つことが難しい
- 非効率なスケーリング
- アプリケーションには複数の機能が備わっており、特定機能へのユーザーアクセスが多い
- このアクセスが集中している機能をスケールしたいが、一つにまとまっていることでスケール不要の機能までスケールする必要がある
- テスト/ビルドに要する時間が長い
- 1行のソース変更を実施した後のテストやビルドが長くなる
マイクロサービス化がもたらすもの
上記に対して、マイクロサービスになることで期待されることは?
- 変更による影響範囲の局所化
- 機能単位でモジュールを分離することで、ソース変更による影響は変更モジュールに閉じられることになる
- モジュール境界の維持しやすさ
- 独立することで、デプロイやスケーリングが用意
- 自律的なチームによる開発・運用
- それぞれのチームが開発を進めるので、お互いの影響を受けなくなる
- Polyglot(-able)
- 例、phpでコードを書いてるとして、開発を続けてて、別言語のほうが良いのではと考える
- そうなった時にPHP→Goへの変更することが出来る
モノリスの考察
当初の構成を振り返る
LB → App → DB
これをAWSのサービスに置き換えると以下のような構成となる
ALB → App on EC/Container →Aurora(MySQL)
その後、上記の構成にキューイングサービスやSNS、細かい点でLambdaなど複数のAWSサービスを 導入する。
しかし、サービスとして処理時間が長くなっていることが判明して時間がかかったこと箇所(ボトルネック)を捜索することになるが多種のサービスを利用していると確認が難しい。
見える範囲での考慮でも複数箇所でボトルネックが発生している懸念が見えてくる
- ①ALB - APP
- ②App - RDS
- ③App - SQS
- ④ ...etc
このような場面に直面した時に役に立つのがAWS X-Rayとなる。
AWS X-Ray
- 分散アプリケーション分析と調査のための分散トレーシング
- サービス間通信の可視化
- エラー原因のサービス発見
- パフォーマンス上のボトルネックを発見
AWS X-Rayにて各AWSサービスごとの通信やエラーなどを可視化することで、ボトルネック部分を見つける手助けとなる。
マイクロサービス
マイクロサービスにはいくつかの課題があり、整理してみる
マイクロサービスの課題
- サービスの適切な分割
- 各機能の分割の仕方は適切なのか、正解はない
- 世の中にはドメイン駆動設計のようなプラクティスがある
- サービスの分割が難しいのは正解がないこと
- 背景や条件によって、解が変わる
- テストの難しさ
- 結合テスト・インテグレーションテストが難しい
- 全ての環境を揃えてのインテグレーションテストは用意する材料が多くて難しい
- インフラレイヤーだけでもCfnやTerraformなどで定義する必要がある
- 影響範囲を時サービス内に収める難しさ
- 他チームを無視して良いわけじゃない
- 自チームが開発しているAPIを他チームが呼び出している可能性を考慮して、他チームに影響を与えるような対応を行ってはいけない
- サービス間の信頼性(Reliablity)
- 「どこ」から「どこへ」の通信を可視化するのか
- マイクロサービスは一種の分散システム
- ネットワーク経由の通信 = 失敗が前提
- 一時的なネットワーク状況による失敗
- 対向サービスの不具合、停止による失敗
- 防御的な実装の必要性(必要なこと)
- 呼び出し先のサービスの位置は一定ではない
- 呼び出し先のサービスが常に一つのアクセス先に限らず、IPアドレスが変更されることを懸念する
- サービスディスカバリ
- サービスの位置をエクセルで作成した台帳で管理する時代からDNSの名前解決で特定する
- 一時的な呼び出しの失敗
- リトライする機構が必要
- リトライする幅も自チームのサービスのみか?または別チーム開発の処理までリトライする必要があるのか?を考慮する
- 継続した呼び出しの失敗
- サーキットブレーカー
- 呼び出し先が不安定な時、呼び出し元はアクセスや処理を止めるべきである
- これは対向システムの復旧に影響を会える(邪魔になる)可能性がある
- 呼び出し先サービスのパフォーマンス悪化
- タイムアウトの実装
- 対向先のデプロイ中などの要因が挙げられる
- 呼び出し元システムの不具合
- 自チームが行っているシステムの振る舞いに関しても考慮する
- 自チームに投げられるリクエストでAPIの仕様に則ってない、400のみを延々投げてくるものがある
- このような場合に対して、一定のレートを超えたリクエストを受けた際にスロットリングしてエラーを返すような機構が必要
- 呼び出し先のサービスの位置は一定ではない
- 防御的な実装の必要性(必要なこと)
マイクロサービスの課題を解決するためには?
マイクロサービスで成功するヒント
- 疎結合な実装を保つこと、自律的なチーム関係の維持が成功の秘訣
- サービス間通信の信頼性担保やシステム全体を観測できる仕組みが必要
- しかし、一貫した実装として密結合ということになりがちで、密結合になった時点でマイクロサービスのメリットを殺してしまう
- マイクロサービス郡は1つのシステムとして認識される
- マイクロサービス郡の中の失敗は、「どこで」「なぜ起きたのか」を調べる必要がある
- システム全体で観測できる実装が必要となる
- ログ/メトリクス/トレース情報出力
- 各サービスの既存実装の出力フォーマットが不揃いだとコンテキストが見えない -アプリケーションごとに出力しているログフォーマットのバラつきが発生する可能性があるので整えることを目指す
しかし、「ログ/メトリクス/トレース情報出力」、「出力フォーマットの統一化」は実現が可能なのか?
- これらを一貫性ある実現方法が必要となる
- 各サービスの個別実装
- 複数のフレームワーク
- 実装担当と品質担保方法
- 統一フォーマットの変更
アプローチ①:共通ライブラリを使用する
システム全体の管理チームで共通ライブラリを開発し、各チームへ共有することで統合的な実装を可能にするアプローチ その中にはいくつかの懸念が生まれる
アプリケーション開発側
- 各チームがアプリケーションに実装
- 共通ライブラリにサービスディスカバリなどの処理をすべて入れておいて、開発チームに提供を行う
- これってアプリケーションの改修が必要となる?
- ログとかモニタリングを備えてるから競合する懸念...
- 今日つライブラリを入れたらパフォーマンスが遅くなった...
- 特定言語のアップデートでライブラリが使えない、そもそも存在しない...
共通ライブラリ側
- ライブラリを入れていないらしい
- 最新ライブラリをいれてないらしい
アプローチ②:プロキシを使う
- アプリケーションからプロキシを経由することでアプリケーションの密結合をやめる方法
- これをサービスメッシュと呼ばれる
サービスメッシュの存在
- 動きとしては、アプリケーションはプロキシ(サービスメッシュ)を通過して通信する
- Envoy
- OSSとして提供されており、多くのインテグレーションにサポート
- 本番環境での利用実績が多い
- 設定ファイルをyaml形式で定義する
- プロキシを運用するには2種類のチームが存在することになることで設定ファイルへの差異が発生する懸念が発生する
- EnvoyProxyの管理は中央管理チームで行う
- アプリケーションを管理してるのは各開発チーム
- 複数アプリケーションで別々の設定ファイルが使用されるEnvoyを使用することでバラつきが出てくる
- このバラつきを動的設定として考え、集中管理チームでEnvoyの設定ファイル差異を解決するのがAWS AppMeshとしている
AWS AppMesh
- AWS App Meshはサービスメッシュのマネージドコントロールプレーンとして存在する
- マイクロサービス郡で利用されているサービスメッシュ全体の構造を定義する
- サービスメッシュを構成するプロキシに対して動的に設定を配信する
- リトライの設定変更などを配信する
- アプリケーションレベルのネットワーク
- ログ/メトリクス/トレースを出力
- トラフィックルーティングポリシー
- ...etc
詳細な実現できることは以下をご参照頂ければと思います。
サービスメッシュは本当に必要なのか?
- あなたのシステムにとってサービスメッシュが必要なのか?
- サービスメッシュは「サービス間通信の信頼性と可観測性を各所売る一貫性ある手段の一つ」
- AWS AppMesh
- サービスメッシュのマネージドコントロールプレーンを担っている
- クラスタやサービスにまたがって動的メッシュを維持できる
- 課題に対する必要性を検討するべき
- そもそもサービスメッシュは必要なのか?
- X-Rayでの分散トレーシングやALBのトラフィックコントロールによって改善/解決出来ないだろうか?
- 共有ライブラリの利用で十分ではないか?
- 動的サービスメッシュが必要性
- Envoyに共通の設定ファイルを入れるのではダメなのか?
- 中央管理チームにて管理が実現できる規模であれば、AppMeshを利用せずにEnvoyProxyの運用に留めることも視野に入れる
最後に
単純にサービスメッシュがなんたるや?というお話ではなく、サービスメッシュ自体がなぜ必要なのか、そもそもの組織としてマイクロサービスに取り組んだ時に起きるであろう事象を交え、 ポイント毎の解決策をお話し頂いたありがたいセッションでした。 サービスの品質やペースを促進することを目的としたはずが、体制やユーザー増加のようなローンチ時に想定しない出来事は多くあると思います。 そのような時に直面したマイクロサービスが提案されることの背景や進めた場合での課題がわかりやすくまとまっておりましたので、良いサービスを継続提供する考慮点として繰り返し考えていこうと思います。